package com.fourpigeon.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.fourpigeon.dao.FollowDao;
import com.fourpigeon.dao.UserDao;
import com.fourpigeon.domain.*;
import com.fourpigeon.service.FollowService;
import com.fourpigeon.utils.IdGenerator;
import com.fourpigeon.utils.UserHolder;
import jakarta.annotation.Resource;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.fourpigeon.utils.RedisConstants.FOLLOWS_KEY;
import static com.fourpigeon.utils.RedisConstants.FOLLOWS_LOCK;

@Service
public class FollowServiceImpl implements FollowService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private FollowDao followDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private IdGenerator idGenerator;

    /**
     * 关注/取关操作
     * @param followUserId 目标用户
     * @return 结果信息
     */
    @Override
    public Result follow(Long followUserId) {
        Long userId = UserHolder.getUser().getId();
        //关注自己
        if(followUserId.equals(userId)) return Result.ok();
        //分布式锁操作
        Boolean isSuccess = stringRedisTemplate.opsForValue().setIfAbsent(FOLLOWS_LOCK + userId, "");
        Boolean isFollow = followOrNot(followUserId);
        //未关注
        if (!isFollow){
            User user = userDao.getById(followUserId);
            if (user == null) {
                return Result.fail("用户不存在!");
            }
            String icon = user.getIcon();
            //创建对象
            Follow follow = new Follow(idGenerator.nextFollowId(), userId, followUserId, icon, LocalDateTime.now());
            //MySQL操作
            if (Boolean.TRUE.equals(isSuccess) &&followDao.save(follow)) {
                stringRedisTemplate.expire(FOLLOWS_LOCK+userId,10L, TimeUnit.SECONDS);
                //MySQL操作
                userDao.addFollowee(userId);    //当前用户关注+1
                userDao.addFans(followUserId);  //被关注者粉丝+1
                //Redis操作
                stringRedisTemplate.opsForSet().add(FOLLOWS_KEY+userId.toString(),followUserId.toString());
            }
        }
        //已关注
        else{
            //MySQL操作
            if (Boolean.TRUE.equals(isSuccess) &&followDao.deleteByUserIdAndFollowId(userId,followUserId)) {
                stringRedisTemplate.expire(FOLLOWS_LOCK+userId,10L, TimeUnit.SECONDS);
                //MySQL操作
                userDao.subFollowee(userId);    //当前用户关注-1
                userDao.subFans(followUserId);  //被关注者粉丝-1
                //Redis操作
                stringRedisTemplate.opsForSet().remove(FOLLOWS_KEY+userId.toString(),followUserId.toString());

            }
        }
        //释放锁
        stringRedisTemplate.delete(FOLLOWS_LOCK+userId);
        return Result.ok(!isFollow);
    }

    /**
     * 是否关注
     * @param tarId 目标用户id
     * @return 结果信息
     */
    @Override
    public Result isFollow(Long tarId) {
        Long userId = UserHolder.getUser().getId();
        if (followDao.isFollow(userId,tarId) == null){
            return Result.ok(false);
        }
        return Result.ok(true);
    }

    public boolean followOrNot(Long tarId){
        Long userId = UserHolder.getUser().getId();
        if (followDao.isFollow(userId,tarId) == null){
            return false;
        }
        return true;
    }

    /**
     * 获取当前用户的所有关注
     * @return UserDTO的List
     */
    @Override
    public Result myFollows() {
        Long userId = UserHolder.getUser().getId();
        //查询数据库
        List<Follow> follows = followDao.getByUserId(userId);
        List<FollowDTO> result = new ArrayList<>();
        for (Follow follow : follows) {
            FollowDTO followDTO = BeanUtil.copyProperties(follow, FollowDTO.class);
            User followUser = userDao.getById(followDTO.getFollowUserId());
            followDTO.setFollowUserSex(followUser.getSex());
            followDTO.setFollowUserName(followUser.getName());
            result.add(followDTO);
        }
        //处理头像临时链接
        for (FollowDTO follow : result) {
            follow.handlerImgs();
        }
        //返回结果
        return Result.ok(result,((Integer)result.size()).longValue());
    }

    /**
     * 查询目标用户的所有关注
     * @param userId 目标用户id
     * @return 结果数据
     */
    @Override
    public Result tarFollows(Long userId) {
        //查询数据库
        List<Follow> follows = followDao.getByUserId(userId);
        List<FollowDTO> result = new ArrayList<>();
        for (Follow follow : follows) {
            //复制属性
            FollowDTO followDTO = BeanUtil.copyProperties(follow, FollowDTO.class);
            User followUser = userDao.getById(followDTO.getFollowUserId());
            //设置属性
            followDTO.setFollowUserSex(followUser.getSex());
            followDTO.setFollowUserName(followUser.getName());
            //加入列表
            result.add(followDTO);
        }
        //处理头像临时链接
        for (FollowDTO follow : result) {
            follow.handlerImgs();
        }
        //返回结果
        return Result.ok(result,((Integer)result.size()).longValue());
    }

    /**
     * 获取当前用户粉丝
     * @return 结果数据
     */
    @Override
    public Result myFollowers() {
        Long userId = UserHolder.getUser().getId();
        //查询数据库
        List<Follow> followers = followDao.getFollowers(userId);
        List<FollowerDTO> result = new ArrayList<>();
        for (Follow follow : followers) {
            //复制属性
            FollowerDTO followerDTO = BeanUtil.copyProperties(follow, FollowerDTO.class);
            User followUser = userDao.getById(followerDTO.getUserId());
            //设置属性
            followerDTO.setFollowerUserIcon(followUser.getIcon());
            followerDTO.setFollowerUserSex(followUser.getSex());
            followerDTO.setFollowerUserName(followUser.getName());
            //加入列表
            result.add(followerDTO);
        }
        //处理头像临时链接
        for (FollowerDTO follow : result) {
            follow.handlerImgs();
        }
        //返回结果
        return Result.ok(result,((Integer)result.size()).longValue());
    }

    /**
     * 获取目标用户的粉丝
     * @param tarId 目标用户id
     * @return 结果数据
     */
    @Override
    public Result tarFollowers(Long tarId) {
        //查询数据库
        List<Follow> followers = followDao.getFollowers(tarId);
        List<FollowerDTO> result = new ArrayList<>();
        for (Follow follow : followers) {
            //复制属性
            FollowerDTO followerDTO = BeanUtil.copyProperties(follow, FollowerDTO.class);
            User followUser = userDao.getById(followerDTO.getUserId());
            //设置属性
            followerDTO.setFollowerUserIcon(followUser.getIcon());
            followerDTO.setFollowerUserSex(followUser.getSex());
            followerDTO.setFollowerUserName(followUser.getName());
            //加入列表
            result.add(followerDTO);
        }
        //处理头像临时链接
        for (FollowerDTO follow : result) {
            follow.handlerImgs();
        }
        //返回结果
        return Result.ok(result,((Integer)result.size()).longValue());
    }

    /**
     * 获取用户的共同关注
     * @param tarId 目标用户
     * @return 结果信息
     */
    @Override
    public Result getCommonFollows(Long tarId) {
        Long userId = UserHolder.getUser().getId();
        String key1 = "follows:"+userId;
        String key2 = "follows:"+tarId;
        Set<String> intersect = stringRedisTemplate.opsForSet().intersect(key1, key2);
        //无共同好友
        if (intersect == null||intersect.isEmpty()) {
            return Result.ok(Collections.emptyList());
        }
        //解析Set，提取id，存储到List中
        List<Long> ids = intersect.stream().map(Long::valueOf).collect(Collectors.toList());
        List<FollowDTO> result = new ArrayList<>();
        //处理结果
        for (Long id : ids) {
            User user = userDao.getById(id);
            FollowDTO temp = new FollowDTO(id,user.getName(),user.getSex(),user.getIcon());
            //处理图片链接
            temp.handlerImgs();
            result.add(temp);
        }
        return Result.ok(result,((Integer)result.size()).longValue());
    }
}
